// -*- mode: c++; indent-tabs-mode: nil; -*-
//
//The Biomolecule Toolkit (BTK) is a C++ library for use in the
//modeling, analysis, and design of biological macromolecules.
//Copyright (C) 2005-2006, Tim Robertson <kid50@users.sourceforge.net>
//
//This program is free software; you can redistribute it and/or modify
//it under the terms of the GNU Lesser General Public License as published
//by the Free Software Foundation; either version 2.1 of the License, or (at
//your option) any later version.
//
//This program is distributed in the hope that it will be useful,  but
//WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//Lesser General Public License for more details.
//
//You should have received a copy of the GNU Lesser General Public License
//along with this program; if not, write to the Free Software Foundation,
//Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#include <iostream>
#include <fstream>

#include <boost/detail/lightweight_test.hpp>

#include <btk/core/atoms/pdb_atom.hpp>
#include <btk/core/molecules/monomer.hpp>
#include <btk/core/molecules/polymer.hpp>
#include <btk/core/io/pdb_system.hpp>

using std::cerr;
using std::endl;

typedef BTK::ATOMS::PDBAtom atom;
typedef BTK::MOLECULES::Monomer<atom> monomer;
typedef BTK::MOLECULES::Polymer<monomer> polymer;
typedef BTK::IO::PDBSystem<polymer> pdb_system;

template <typename T>
bool equal(T const & v1, T const & v2) {
  if (v1 == v2) return true;

  std::cerr << "v1: " << v1 
            << " v2: " << v2 << std::endl;
  return false;
}

bool atoms_mostly_equivalent(atom const & a1,
                             atom const & a2)
{
  // make sure that a1 and a2 are equal in every way except numbering.
  if (!equal(a1.position(),a2.position())) return false;
  if (!equal(a1.type(),a2.type())) return false;
  if (!equal(a1.name(),a2.name())) return false;
  if (!equal(a1.element_type(),a2.element_type())) return false;

  if (!equal(a1.element_name(),a2.element_name())) return false;
  if (!equal(a1.res_name(),a2.res_name())) return false;
  if (!equal(a1.chain_id(),a2.chain_id())) return false;
  if (!equal(a1.insert_code(),a2.insert_code())) return false;
  if (!equal(a1.occupancy(),a2.occupancy())) return false;
  if (!equal(a1.b_factor(),a2.b_factor())) return false;
  if (!equal(a1.is_hetatom(),a2.is_hetatom())) return false;

  return true;
}

int main()
{
  pdb_system original("test.short.pdb",
                      true);

  {
    // read in a file, write it back out as a new file
    std::ofstream pdb_out("output_test.pdb");
    pdb_out << original << endl;
  }

  {
    // read the new file, and compare it to the original
    pdb_system copy("output_test.pdb",
                    true,
                    false,
                    original.get_chemical_type_system());

    pdb_system::atom_iterator ai,aj;

    for (ai = original.structure_begin(), aj = copy.structure_begin();
         ai != original.structure_end() && aj != copy.structure_end();
         ++ai, ++aj) {
      bool t;
      BOOST_TEST(t = atoms_mostly_equivalent(*ai,*aj));
      if (!t)
        cerr << "Unequal atoms:\n" << " " << *ai << " " << *aj << endl;
    }
  }

  return boost::report_errors();
}
